package com.migo.controller;

import com.migo.common.StringSplitUtil;
import com.migo.entity.FirmwareEntity;
import com.migo.entity.SysOssEntity;
import com.migo.entity.SysUserEntity;
import com.migo.mongo.entity.FirmwareUpdateLog;
import com.migo.mongo.service.FirmwareUpdateLogService;
import com.migo.oss.OSSFactory;
import com.migo.service.FirmwareDescriptionService;
import com.migo.service.FirmwareService;
import com.migo.service.SysOssService;
import com.migo.service.SysUserService;
import com.migo.utils.*;
import com.migo.view.UploadDTO;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;

import static com.migo.utils.ShiroUtils.getUserId;
import static com.migo.utils.ZipUtils.unZip;


/**
 * @author powervision
 * @email wes.wang@powervision.me
 * @date 2018-12-25 10:01:01
 */
@RestController
@RequestMapping("firmware")
public class FirmwareController {
    @Autowired
    private FirmwareService firmwareService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysOssService sysOssService;

    @Autowired
    private FirmwareUpdateLogService firmwareUpdateLogService;

    @Autowired
    private FirmwareDescriptionService firmwareDescriptionService;

    @Autowired
    StringRedisTemplate redisTemplate;


    @Autowired
    OSSFactory ossFactory;



    /**
     * 船体固件上传文件
     */
    @RequestMapping("/tempUpload")
    @RequiresPermissions("firmware:tempUpload")
    public R tempUpload(@RequestParam("file") MultipartFile file) throws Exception {
        String fileName = "";
        if (file.isEmpty()) {
            throw new RRException("上传文件不能为空");
        }
        fileName = file.getOriginalFilename();
        if (!fileName.contains(".zip")) {
            throw new RRException("文件格式不正确！");
        }
        // 文件存放服务端的位置
        String rootPath = "/opt/temp";     // /opt/temp   F:\temp
        File dir = new File(rootPath + File.separator + "tmpFiles");
        if (!dir.exists())
            dir.mkdirs();
        String filePath = dir.getAbsolutePath() + File.separator + file.getOriginalFilename();
        // 写文件到服务器
        File serverFile = new File(filePath);
        file.transferTo(serverFile);

        //第一层解压目录
        String uzipPath = dir.getAbsolutePath() + File.separator + file.getOriginalFilename().substring(0, file.getOriginalFilename().indexOf(".zip"));
        //文件第一层解压
        unZip(filePath, uzipPath);
        //删除解压完的第一层源文件
        File sourceFile = new File(filePath);
        sourceFile.delete();
        //获取第一层 uzip中的zip
        Map<String, String> fileMap = ZipUtils.checkFileDirOrName(uzipPath);
        System.out.println(fileMap);
        //解压第二层中的zip
        Iterator<Map.Entry<String, String>> entries = fileMap.entrySet().iterator();

        while (entries.hasNext()) {

            Map.Entry<String, String> entry = entries.next();
            String childfileName = entry.getKey();
            String childPath = entry.getValue();
            System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
            if (childfileName.contains(".zip")) {
                String childFilePath = childPath + File.separator + childfileName;
                String zipPath = childPath + File.separator + childfileName.substring(0, childfileName.indexOf(".zip"));
                ZipUtils.unZip(childFilePath, zipPath);
                File childFile = new File(childFilePath);
                childFile.delete();
            }
        }

        //开始获取解完的所有 上传文件 及规则
        Map<String, String> result = ZipUtils.getFileDirOrName(uzipPath, new HashMap<String, String>());
        System.out.println(JsonUtils.getJSONString(result));

        //上传记录
        List<UploadDTO> uploadList = new ArrayList<>();
        //开始上传 文件
        Iterator<Map.Entry<String, String>> uploadEntries = result.entrySet().iterator();
        while (uploadEntries.hasNext()) {
            UploadDTO uploadDTO = new UploadDTO();
            Map.Entry<String, String> entry = uploadEntries.next();
            String uploadFilePath = entry.getKey();
            String uploadFileParam = entry.getValue();
            File uploadFile = new File(uploadFilePath);
            String fileKey = FileMD5Util.getNewFileMD5(uploadFile);
            String uploadfileName = uploadFile.getName();
            //构建流
            FileInputStream fileStream = new FileInputStream(uploadFile);
            //文件路径
            String uploadPath = System.currentTimeMillis() + "/" + uploadfileName;
            //上传文件
            String url = ossFactory.build().upload(fileStream, uploadPath);
            uploadDTO.setFileKey(fileKey);
            uploadDTO.setFileParam(uploadFileParam);
            uploadDTO.setFilePath(url);
            uploadDTO.setFileSize(uploadFile.length() + "");
            uploadList.add(uploadDTO);
        }
        System.out.print(JsonUtils.getJSONString(uploadList)); //保存到固件信息表中
        //后端循环插入数据--频率低、数量少，暂时使用循环
        for (int i = 0; i < uploadList.size(); i++) {
            FirmwareEntity firmware = new FirmwareEntity();
            UploadDTO uploadEntity = uploadList.get(i);
            String[] params = uploadEntity.getFileParam().split("_");
            String type = params[1].split("-")[0];
            String version = params[1].split("-")[1];
            if (uploadEntity.getFilePath().contains("update.conf")) {
                type = "config";
                version = System.currentTimeMillis() + "";
            }
            firmware.setFirmwareDownloadAddr(uploadEntity.getFilePath());
            firmware.setRowId(uploadEntity.getFileKey());
            firmware.setEquipmentModel(params[0]);
            firmware.setHardwareType(type);
            firmware.setHardwareModel(type);
            firmware.setFirmwareLatestVersionCode(version);
            firmware.setAddTime(DateUtils.getNow());
            firmware.setIsMandatoryUpgrade(0);
            firmware.setFirmwareSize(uploadEntity.getFileSize());
            firmwareService.save(firmware);
        }
//        FileUtils.deleteQuietly(dir);  //删除临时目录
        deleteDir(rootPath);
        return R.ok().put("uploadList", uploadList);
    }


    /**
     * match上传文件
     */
    @RequestMapping("/testAUpload")
    @RequiresPermissions("match:testAUpload")
    public R testAUpload(@RequestParam("file") MultipartFile file) throws Exception {
        String url = uploadMatch("test",file);
        pushMatchFileKey("test",file);  // md5 值push到redis
        return R.ok().put("url",url);
    }


    /**
     * 測試服務器Bmatch上传文件
     */
    @RequestMapping("/testBUpload")
    @RequiresPermissions("match:testBUpload")
    public R testBUpload(@RequestParam("file") MultipartFile file) throws Exception {
        String url = uploadMatch("testb",file);
        pushMatchFileKey("testb",file);  // md5 值push到redis
        return R.ok().put("url",url);
    }


    /**
     * 測評match上传文件
     */
    @RequestMapping("/devUpload")
    @RequiresPermissions("match:devUpload")
    public R devUpload(@RequestParam("file") MultipartFile file) throws Exception {
        String url = uploadMatch("dev",file);
        pushMatchFileKey("dev",file);  // md5 值push到redis
        return R.ok().put("url",url);
    }


    /**
     * 綫上match上传文件
     */
    @RequestMapping("/onlineUpload")
    @RequiresPermissions("match:onlineUpload")
    public R onlineUpload(@RequestParam("file") MultipartFile file) throws Exception {
        String url = uploadMatch("online",file);
        pushMatchFileKey("online",file);  // md5 值push到redis
        return R.ok().put("url",url);
    }

    /**
     * match文件 的MD5值推送到redis，便于后续验证或查询
     * @param key  match 类型
     * @param file 上传的文件
     */
    public void pushMatchFileKey(String key,MultipartFile file){
        String fileKey = FileMD5Util.getMd5(file);
        redisTemplate.boundValueOps(key).set(fileKey);
    }





    /*
        match文件上传
     */
    public String uploadMatch(String path,MultipartFile file) throws IOException {
        String fileName = "";
        if (file.isEmpty()) {
            throw new RRException("上传文件不能为空");
        }

        fileName = file.getOriginalFilename();

        //文件路径
        String uploadPath = path + "/" + fileName;

        //上传文件
        String url = ossFactory.build().uploadMatch(uploadPath,file.getBytes());


        //保存文件信息
        SysOssEntity ossEntity = new SysOssEntity();
        ossEntity.setUrl(url.substring(1,url.length()));
        ossEntity.setCreateDate(new Date());
        sysOssService.save(ossEntity);

        return url;
    }

    /**
     * 船体固件上传文件
     */
    @RequestMapping("/upload")
    @RequiresPermissions("firmware:upload")
    public R upload(@RequestParam("file") MultipartFile file) throws Exception {
        String fileName = "";
        if (file.isEmpty()) {
            throw new RRException("上传文件不能为空");
        }
        fileName = file.getOriginalFilename();
        if (!fileName.contains(".zip")) {
            throw new RRException("文件格式不正确！");
        }
        // 文件存放服务端的位置
        String rootPath = "/opt/temp";     // /opt/temp
        File dir = new File(rootPath + File.separator + "tmpFiles");
        if (!dir.exists())
            dir.mkdirs();
        String filePath = dir.getAbsolutePath() + File.separator + file.getOriginalFilename();
        // 写文件到服务器
        File serverFile = new File(filePath);
        file.transferTo(serverFile);

        //第一层解压目录
        String uzipPath = dir.getAbsolutePath() + File.separator + file.getOriginalFilename().substring(0, file.getOriginalFilename().indexOf(".zip"));
        //文件第一层解压
        unZip(filePath, uzipPath);
        //删除解压完的第一层源文件
        File sourceFile = new File(filePath);
        sourceFile.delete();
        //获取第一层 uzip中的zip
        Map<String, String> fileMap = ZipUtils.checkFileDirOrName(uzipPath);
        System.out.println(fileMap);
        //解压第二层中的zip
        Iterator<Map.Entry<String, String>> entries = fileMap.entrySet().iterator();

        while (entries.hasNext()) {

            Map.Entry<String, String> entry = entries.next();
            String childfileName = entry.getKey();
            String childPath = entry.getValue();
            System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
            if (childfileName.contains(".zip")) {
                String childFilePath = childPath + File.separator + childfileName;
                String zipPath = childPath + File.separator + childfileName.substring(0, childfileName.indexOf(".zip"));
                ZipUtils.unZip(childFilePath, zipPath);
                File childFile = new File(childFilePath);
                childFile.delete();
            }
        }

        //开始获取解完的所有 上传文件 及规则
        Map<String, String> result = ZipUtils.getFileDirOrName(uzipPath, new HashMap<String, String>());
        System.out.println(JsonUtils.getJSONString(result));

        //上传记录
        List<UploadDTO> uploadList = new ArrayList<>();
        //开始上传 文件
        Iterator<Map.Entry<String, String>> uploadEntries = result.entrySet().iterator();
        while (uploadEntries.hasNext()) {
            UploadDTO uploadDTO = new UploadDTO();
            Map.Entry<String, String> entry = uploadEntries.next();
            String uploadFilePath = entry.getKey();
            String uploadFileParam = entry.getValue();
            File uploadFile = new File(uploadFilePath);
            String fileKey = FileMD5Util.getNewFileMD5(uploadFile);
            String uploadfileName = uploadFile.getName();
            //构建流
            FileInputStream fileStream = new FileInputStream(uploadFile);
            //文件路径
            String uploadPath = System.currentTimeMillis() + "/" + uploadfileName;
            //上传文件
            String url = ossFactory.build().upload(fileStream, uploadPath);
            uploadDTO.setFileKey(fileKey);
            uploadDTO.setFileParam(uploadFileParam);
            uploadDTO.setFilePath(url);
            uploadDTO.setFileSize(uploadFile.length() + "");
            uploadList.add(uploadDTO);
        }
        System.out.print(JsonUtils.getJSONString(uploadList)); //保存到固件信息表中
        //后端循环插入数据--频率低、数量少，暂时使用循环
        for (int i = 0; i < uploadList.size(); i++) {
            FirmwareEntity firmware = new FirmwareEntity();
            UploadDTO uploadEntity = uploadList.get(i);
            String[] params = uploadEntity.getFileParam().split("_");
            String type = params[1].split("-")[0];
            String version = params[1].split("-")[1];
            if (uploadEntity.getFilePath().contains("update.conf")) {
                type = "config";
                version = System.currentTimeMillis() + "";
            }
            firmware.setFirmwareDownloadAddr(uploadEntity.getFilePath());
            firmware.setRowId(uploadEntity.getFileKey());
            firmware.setEquipmentModel(params[0]);
            firmware.setHardwareType(type);
            firmware.setHardwareModel(type);
            firmware.setFirmwareLatestVersionCode(version);
            firmware.setAddTime(DateUtils.getNow());
            firmware.setIsMandatoryUpgrade(0);
            firmware.setFirmwareSize(uploadEntity.getFileSize());
            firmwareService.save(firmware);
        }
//        FileUtils.deleteQuietly(dir);  //删除临时目录
        deleteDir(rootPath);
        return R.ok().put("uploadList", uploadList);
    }


    public static boolean deleteDir(String path){
        File file = new File(path);
        if(!file.exists()){//判断是否待删除目录是否存在
            System.err.println("The dir are not exists!");
            return false;
        }

        String[] content = file.list();//取得当前目录下所有文件和文件夹
        for(String name : content){
            File temp = new File(path, name);
            if(temp.isDirectory()){//判断是否是目录
                deleteDir(temp.getAbsolutePath());//递归调用，删除目录里的内容
                temp.delete();//删除空目录
            }else{
                if(!temp.delete()){//直接删除文件
                    System.err.println("Failed to delete " + name);
                }
            }
        }
        return true;
    }

    /**
     * 列表
     */
    @RequestMapping("/list")
    @RequiresPermissions("firmware:list")
    public R list(@RequestParam Map<String, Object> params) {
        //查询列表数据
        Query query = new Query(params);
        List<FirmwareEntity> firmwareList = firmwareService.queryList(query);
        int total = firmwareService.queryTotal(query);

        PageUtils pageUtil = new PageUtils(firmwareList, total, query.getLimit(), query.getPage());

        return R.ok().put("page", pageUtil);
    }


    /**
     * 信息
     */
    @RequestMapping("/info/{id}")
    @RequiresPermissions("firmware:info")
    public R info(@PathVariable("id") Integer id) {
        FirmwareEntity firmware = firmwareService.queryObject(id);

        return R.ok().put("firmware", firmware);
    }

    /**
     * 保存
     */
    @RequestMapping("/save")
    @RequiresPermissions("firmware:save")
    public R save(@RequestBody FirmwareEntity firmware) {
//		String uuid = UUID.randomUUID()+"";
        SysUserEntity user = sysUserService.queryObject(getUserId());
//		firmware.setRowId(uuid);
        firmware.setAddTime(DateUtil.getNow());
        firmware.setAddUser(user.getUsername());
        firmware.setFirmwareLatestVersionCode(StringSplitUtil.getInstance().getLastVersion(firmware.getMergeVersion()));
//        Map<String, String> map = StringSplitUtil.getInstance().getLastVersionMap(firmware.getMergeVersion());
        firmware.setMergeVersion(StringSplitUtil.getInstance().getMergeVersion(firmware.getMergeVersion()));
//        //遥控器固件多个固件zip 区分版本同一条数据
//        for (Map.Entry<String, String> entry : map.entrySet()) {
//            firmware.setHardwareModel(entry.getKey());
//            firmware.setFirmwareLatestVersionCode(entry.getValue());
//            firmwareService.save(firmware);
//        }
        firmwareService.save(firmware);
        return R.ok();
    }

    /**
     * 修改
     */
    @RequestMapping("/update")
    @RequiresPermissions("firmware:update")
    public R update(@RequestBody FirmwareEntity firmware) {
        firmware.setAddTime(DateUtil.getNow());
        firmwareService.update(firmware);
        //存储更新日志
        FirmwareUpdateLog log = new FirmwareUpdateLog();
        BeanUtils.copyProperties(firmware,log);
        firmwareUpdateLogService.save(log);
        return R.ok();
    }

    /**
     * 删除
     */
    @RequestMapping("/delete")
    @RequiresPermissions("firmware:delete")
    public R delete(@RequestBody Integer[] ids) {
        firmwareService.deleteBatch(ids);

        return R.ok();
    }

}
